(function (root, factory) {
  let PubSub = factory();
  root.PubSub = PubSub;

  if (typeof exports === "object") {
    if (module !== undefined && module.exports) {
      exports = module.exports = PubSub;
    }
    exports.PubSub = PubSub;
    module.exports = exports = PubSub;
  } else if (typeof define === "function" && define.amd) {
    define(function () {
      return PubSub;
    });
  }
})((typeof window === "object" && window) || this, function () {
  let messages = {};
  let lastIndex = -1;
  class PubSub {
    static subscribe(type, fn) {
      if (typeof fn !== "function") return false;
      if (!Object.prototype.hasOwnProperty.call(messages, type)) {
        messages[type] = {};
      }
      lastIndex++;
      let token = "uuid_" + lastIndex;
      messages[type][token] = fn;
      return token;
    }
    static publish(type, data) {
      if (!Object.prototype.hasOwnProperty.call(messages, type)) return;
      let typeFns = messages[type];
      for (const key in typeFns) {
        if (Object.prototype.hasOwnProperty.call(typeFns, key)) {
          typeFns[key](type, data);
        }
      }
    }
    static unSubscribe(token) {
      for (const key in messages) {
        if (key === token && Object.hasOwnProperty.call(messages, key)) {
          delete messages[key];
        } else {
          let typeFns = messages[key];
          for (const typeFnKey in typeFns) {
            if (Object.hasOwnProperty.call(typeFns, typeFnKey)) {
              if (typeFnKey === token) {
                console.log(typeFnKey, token);
                delete typeFns[typeFnKey];
              }
            }
          }
        }
      }
      console.log(messages);
    }
  }
  return PubSub;
});
